package com.mk.cloud.common.service.core;

import act.controller.Controller;
import cn.hutool.core.io.FileTypeUtil;
import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import com.mk.cloud.common.config.AppConfig;
import org.osgl.mvc.annotation.With;
import org.osgl.util.S;import com.mk.cloud.common.util.S2;
import org.osgl.mvc.annotation.Action;
import org.osgl.mvc.annotation.GetAction;
import org.osgl.mvc.annotation.PostAction;
import org.osgl.mvc.result.RenderBinary;
import org.osgl.mvc.result.Result;
import org.osgl.util.C;
import org.osgl.util.IO;

import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unused")
@Controller("file")
public class FileService extends Controller.Base {
    @Action("up-token.json")
    public Result uploadToken() {
        String token = S2.UUID();
        return renderJson(C.Map("token", token));
    }

    @Action("token.html")
    public Result file_token() {
        return renderJson(C.Map("uptoken", S2.UUID()));
    }

    @GetAction("download/{key}.html")
    public Result file_download(String key, String t) {
        File file = new File(getPath(key));
        notFoundIfNot(file.exists());
        byte[] contextx = IO.readContent(file);
        context.resp().addHeader("Content-Length",contextx.length + "");
        return new RenderBinary(file, S2.electOneNotBlank(t, file.getName()), false);
    }

    @PostAction("upload/common.html")
    public Result upload(File file) {
        return renderJson(checkAndSaveFile(file));
    }

    private String getPath(String key) {
        String path = AppConfig.qiniu.path.get();
        if(System.getProperty("os.name").toLowerCase().contains("windows")){
            path = S2.replaceReg(path, "file:/", "");
        }else{
            path = S2.replaceReg(path, "file:", "");
        }
        if (!S.endsWith(path, File.separator)) return path + File.separator + key;
        else return path + key;
    }

    private Map<String, Object> checkAndSaveFile(File file) {
        byte[] bytes = IO.readContent(file);
        byte[] hashs = new byte[0];
        try {
            hashs = MessageDigest.getInstance("MD5").digest(bytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        StringBuilder o = new StringBuilder(hashs.length * 3);
        for (byte aBuf : hashs) {
            int n = aBuf & 0xff;
            if (n < 0x10)
                o.append("0");
            o.append(Long.toString(n, 16).toUpperCase());
        }
        String key = o.toString();

        ContentInfoUtil util = new ContentInfoUtil();
        ContentInfo info = util.findMatch(bytes);
        key += "." + info.getFileExtensions()[0];

        File old_file = new File(getPath(key));
        if (!old_file.exists()) {
            try {
                badRequestIfNot(old_file.createNewFile());
                IO.write(bytes, old_file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        file.deleteOnExit();
        return C.Map(
            "key", key,
            "hash", key, "size",
            bytes.length,
            "state", "SUCCESS",
            "original", key,
            "title", file.getName(),
            "url", "/file/view/" + key);
    }

    private String getPath(String key,String path) {
        if(System.getProperty("os.name").toLowerCase().contains("windows")){
            path = S2.replaceReg(path, "file:/", "");
        }else{
            path = S2.replaceReg(path, "file:", "");
        }
        if (!S.endsWith(path, File.separator)) return path + File.separator + key;
        else return path + key;
    }

    private Map<String, Object> checkAndSaveFile(File file,String path,String filetype) {
        byte[] bytes = IO.readContent(file);
        byte[] hashs = new byte[0];
        try {
            hashs = MessageDigest.getInstance("MD5").digest(bytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        StringBuilder o = new StringBuilder(hashs.length * 3);
        for (byte aBuf : hashs) {
            int n = aBuf & 0xff;
            if (n < 0x10)
                o.append("0");
            o.append(Long.toString(n, 16).toUpperCase());
        }
        String key = o.toString();
        String type = FileTypeUtil.getType(file);
        ContentInfoUtil util = new ContentInfoUtil();
        ContentInfo info = null;
        try {
            info = util.findMatch(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        key += "." + info.getFileExtensions()[0];
        // key+= "." + type;
        File old_file = new File(getPath(key,path));
        if (!old_file.exists()) {
            try {
                badRequestIfNot(old_file.createNewFile());
                IO.write(bytes, old_file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        file.deleteOnExit();
        return C.Map(
                "key", key,
                "hash", key, "size",
                bytes.length,
                "state", "SUCCESS",
                "original", key,
                "title", file.getName(),
                "url", "/file/"+filetype+"/" + key);
    }



    @PostAction("upload/wang.html")
    public Result uploadForWangeditor(List<File> file) {
        List<String> urls = new ArrayList<>();
        file.forEach(afile -> urls.add(checkAndSaveFile(afile,AppConfig.qiniu.path.get(), "view").get("url").toString()));
        return renderJson(C.Map("errno", 0, "data", urls));
    }

}
